package com.exam.api.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.exam.api.common.*;
import com.exam.api.dto.*;
import com.exam.api.service.*;
import com.exam.api.vo.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.math.BigDecimal;
import java.util.*;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.stream.Collectors;

import com.exam.api.common.BaseSelectEntity;
import cn.hutool.core.collection.CollectionUtil;

/**
 * @description: 分数详情对外接口层
 * @author: wuming
 * @create: 2024.05.03 13:24:03
 */
@RestController
@RequestMapping("/examDetail")
public class ExamDetailController extends BaseController<ExamDetailService, ExamDetailDTO> {

    @Value("${new-tomcat.folder}")
    private String newTomcatFolder;

    @Autowired
    private StudentService studentService;

    @Autowired
    private ExamService examService;

    @Autowired
    private ExamStudentService examStudentService;

    @Autowired
    private QuestionsService questionsService;

    @Override
    @Resource(name = "examDetailService")
    protected void setBaseService(ExamDetailService examDetailService) {
        this.baseService = examDetailService;
    }

    /**
     * 默认分页查询
     *
     * @param examDetailDTO
     * @return
     */
    @PostMapping("/page")
    public ReturnMsg page(@RequestBody ExamDetailDTO examDetailDTO) {
        return ReturnMsg.ok(baseService.basePage(examDetailDTO));
    }

    @PostMapping("/pagegrade")
    public ReturnMsg pageGrade(@RequestBody ExamDetailDTO examDetailDTO) {
        // 获取分页数据
        Page<ExamDetailDTO> page = baseService.basePage(examDetailDTO);

        // 提取 questionIds 列表
        List<Long> questionIds = page.getRecords().stream()
                .map(ExamDetailDTO::getQuestionId)
                .distinct() // 去重
                .collect(Collectors.toList());

        // 创建一个 Map，用于存储 questionId 和对应的 types
        Map<Long, Integer> questionIdToTypeMap = new HashMap<>();

        // 遍历 questionIds，获取每个 questionId 对应的 types
        for (Long questionId : questionIds) {
            QuestionsDTO questionsDTO = questionsService.getById(questionId);
            if (questionsDTO != null) {
                questionIdToTypeMap.put(questionId, questionsDTO.getTypes());
            }
        }

        // 遍历分页数据，将 types 设置到对应的 ExamDetailDTO 中
        for (ExamDetailDTO record : page.getRecords()) {
            Long questionId = record.getQuestionId();
            if (questionIdToTypeMap.containsKey(questionId)) {
                record.setTypes(questionIdToTypeMap.get(questionId));
            }
        }

        // 返回成功响应
        return ReturnMsg.ok(page);
    }


    @PostMapping("/saveData")
    public ReturnMsg saveData(@RequestBody ExamDetailDTO examDetailDTO) throws FileNotFoundException {
        // 先删除之前的
        LambdaQueryWrapper<ExamDetailDTO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ExamDetailDTO::getExamId, examDetailDTO.getExamId());
        queryWrapper.eq(ExamDetailDTO::getStudentId, examDetailDTO.getStudentId());
        this.baseService.remove(queryWrapper);
        MyThreadLocal.set(examDetailDTO.getExamId() + "-" + examDetailDTO.getStudentId());
        File file = new File(newTomcatFolder + examDetailDTO.getUrl());
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        EasyExcel.read(inputStream, StuQuestionVO.class, new ExcelListener()).sheet().doRead();
        MyThreadLocal.remove();
        return ReturnMsg.ok();
    }

    @PostMapping("/saveAnswer")
    public ReturnMsg saveAnswer(@RequestBody List<ExcelVO> answer,@RequestParam("studentName") String studentName){
        // 生成一个唯一的文件名，包含学生姓名
        String fileName = studentName + "_" + System.currentTimeMillis() + ".xlsx";
        File file = new File(newTomcatFolder + fileName);
        //创建excel文件
        try {
            EasyExcel.write(file, ExcelVO.class).sheet("学生答题").doWrite(answer);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ReturnMsg.ok();
    }

    @PostMapping("/saveBatch")
    public ReturnMsg saveBatch(@RequestBody List<ExamDetailDTO> list) {
        // 先删除之前的
        if (CollectionUtil.isNotEmpty(list)) {
            ExamDetailDTO examDetailDTO = list.get(0);
            LambdaQueryWrapper<ExamDetailDTO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ExamDetailDTO::getExamId, examDetailDTO.getExamId());
            queryWrapper.eq(ExamDetailDTO::getStudentId, examDetailDTO.getStudentId());
            this.baseService.remove(queryWrapper);
        }
        for (ExamDetailDTO examDetailDTO : list) {
            examDetailDTO.setCreateTime(new Date());
        }
        return ReturnMsg.ok(baseService.saveBatch(list));
    }


    @GetMapping("/detail/{examId}")
    public ReturnMsg getEchartsById(@PathVariable Long examId) throws Exception {
        LambdaQueryWrapper<ExamStudentDTO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ExamStudentDTO::getExamId, examId);
        int count = examStudentService.count(queryWrapper);
        if (count == 0) throw new Exception("此次考试没有同学参与");
        List<InfoVO> info = baseService.getInfo(examId);
        if (CollectionUtil.isEmpty(info) || info.size() != count) throw new Exception("此次考试成绩录入不完整");
        EchartsVO echartsVO = new EchartsVO();
        echartsVO.setMaxStudent(info.get(info.size() - 1));
        echartsVO.setMinStudent(info.get(0));
        double total = 0d;
        int total0_60 = 0, total60_80 = 0, total80_95 = 0, total95 = 0;
        for (InfoVO infoVO : info) {
            double grade = Double.parseDouble(infoVO.getGrade());
            total += grade;
            if (grade < 60) {
                total0_60 += 1;
            }
            if (60 <= grade && grade < 80) {
                total60_80 += 1;
            }
            if (80 <= grade && grade < 95) {
                total80_95 += 1;
            }
            if (95 <= grade) {
                total95 += 1;
            }

        }
        echartsVO.setAvgGrade(total / info.size());
        List<GradeVO> gradeListRange = new ArrayList<>();
        gradeListRange.add(new GradeVO("0-60", total0_60));
        gradeListRange.add(new GradeVO("60-80", total60_80));
        gradeListRange.add(new GradeVO("80-95", total80_95));
        gradeListRange.add(new GradeVO("95-100", total95));
        echartsVO.setGradeListRange(gradeListRange);
        List<QuestionVO> questionVOS = baseService.getQuestion(examId);
        echartsVO.setQuestionVOS(questionVOS);
        echartsVO.setGradeList(info);
        ExamDetailDTO examDetailDTO = new ExamDetailDTO();
        examDetailDTO.setExamId(examId);

        List<ExamDetailDTO> list = this.baseService.findList(examDetailDTO);
        Map<Long, List<ExamDetailDTO>> collect = list.stream().collect(Collectors.groupingBy(ExamDetailDTO::getQuestionId));
        List<QuestionErrorVO> questionErrorVOS = new ArrayList<>();
        for (Map.Entry<Long, List<ExamDetailDTO>> longListEntry : collect.entrySet()) {
            List<ExamDetailDTO> entryValue = longListEntry.getValue();
            int i = 0;
            String questionName = "";
            for (ExamDetailDTO detailDTO : entryValue) {
                questionName = detailDTO.getQuestionName();
                if (!detailDTO.getGrade().equals(detailDTO.getQuestionGrade())) {
                    i++;
                }
            }
            QuestionErrorVO questionErrorVO = new QuestionErrorVO();
            questionErrorVO.setQuestionId(longListEntry.getKey());
            questionErrorVO.setQuestionName(questionName);
            questionErrorVO.setValue(i);
            questionErrorVOS.add(questionErrorVO);
        }
        echartsVO.setErrorVOS(questionErrorVOS);
        return ReturnMsg.ok(echartsVO);
    }


    /**
     * 根据XML中的sql语句进行查询
     *
     * @param examDetailDTO
     * @return
     */
    @PostMapping(value = "/findList")
    public ReturnMsg findList(@RequestBody ExamDetailDTO examDetailDTO) {
        return ReturnMsg.ok(baseService.findList(examDetailDTO));
    }

    @Override
    protected void beforeSave(ExamDetailDTO entity) throws Exception {
        entity.setCreateTime(new Date());
        super.beforeSave(entity);
    }

    @GetMapping("/all/student")
    public ReturnMsg allStudent() {
        List<BaseSelectEntity> list = new ArrayList<>();
        List<StudentDTO> dtos = studentService.list();
        for (StudentDTO dto : dtos) {
            BaseSelectEntity baseSelectEntity = new BaseSelectEntity();
            baseSelectEntity.setKey(dto.getId());
            baseSelectEntity.setValue(dto.getName());
            list.add(baseSelectEntity);
        }
        return ReturnMsg.ok(list);
    }

    @GetMapping("/all/exam")
    public ReturnMsg allExam(@RequestParam(required = false) Long teacherId) {
        List<BaseSelectEntity> list = new ArrayList<>();
        LambdaQueryWrapper<ExamDTO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (teacherId != null) {
            lambdaQueryWrapper.eq(ExamDTO::getTeacherId, teacherId);
        }
        List<ExamDTO> dtos = examService.list(lambdaQueryWrapper);
        for (ExamDTO dto : dtos) {
            BaseSelectEntity baseSelectEntity = new BaseSelectEntity();
            baseSelectEntity.setKey(dto.getId());
            baseSelectEntity.setValue(dto.getExamName());
            list.add(baseSelectEntity);
        }
        return ReturnMsg.ok(list);
    }

    @GetMapping("/all/questions")
    public ReturnMsg allQuestions() {
        List<BaseSelectEntity> list = new ArrayList<>();
        List<QuestionsDTO> dtos = questionsService.list();
        for (QuestionsDTO dto : dtos) {
            BaseSelectEntity baseSelectEntity = new BaseSelectEntity();
            baseSelectEntity.setKey(dto.getId());
            baseSelectEntity.setValue(dto.getQuestionName());
            list.add(baseSelectEntity);
        }
        return ReturnMsg.ok(list);
    }

}

